package com.freestyle.nettychat.client;


import com.freestyle.netty.easynetty.client.interfaces.IGeneralClient;
import com.freestyle.netty.easynetty.lock.interfaces.PromiseUtil;
import com.freestyle.nettychat.chat.ChatCommand;
import com.freestyle.nettychat.chat.CodeConsts;
import com.freestyle.nettychat.chat.dto.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * Created by rocklee on 2022/2/6 11:15
 */
public class ClientRoutine {
  private ChannelHandlerContext ctx;
  private String room=null;
  private String uid=null;
  private PromiseUtil<JSONData> promiseUtil;
  private IGeneralClient client;
  public ClientRoutine(PromiseUtil<JSONData> promiseUtil) {
    this.promiseUtil=promiseUtil;
  }
  public PromiseUtil<JSONData> getPromiseUtil(){
    return promiseUtil;
  }
  public void setClient(IGeneralClient client){
    this.client=client;
  }

  public String getRoom() {
    return room;
  }

  public void setRoom(String room) {
    this.room = room;
  }

  public String getUid() {
    return uid;
  }

  public void setUid(String uid) {
    this.uid = uid;
  }

  public ClientRoutine(){

  }
  public  void showPrompt(){
    System.out.println();
    if (room == null || uid == null) {
      System.out.print((uid==null?"":uid+"@") + ">>");
    }
    else{
      System.out.print(uid + "@" + room + ":");
    }
  }
  private Channel checkChannel(){
    if (!client.isConnected()){
      try {
        client.connect();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    return client.getChannel();
  }
  public JSONData sendCommand (String command,boolean... await){
    String[] args=command.replaceAll("\\s{1,}", " ").split(" ");
    boolean flag=await.length>0&&await[0];
    try {
      long id=promiseUtil.newLock(JSONData.class);
      ChatCommand chatCommand=ChatCommand.fromValue(args[0]);
      if (chatCommand==null){
        output("无效指令");
        showHelp();
        return null;
      }
      switch (chatCommand){
        case createRoom:
          createRoom(id,args[1]);
          break;
        case login:
          login(id,args[1],args[2]);
          break;
        case enterRoom:
          enterRoom(id,args[1]);
          break;
        case removeChatRoom:
          removeChatRoom(id,args[1]);
          break;
        case help:
          showHelp();
          break;
        case logout:
          logout(id);
          break;
        case fetchFile:
          fetchFile(id,args[1]);
          break;
        case getOnLineUserList:
          if (args.length==1)
            getOnLineUserList(id);
          else
            getOnLineUserList(id,args[1]);
          break;
        case getOnLineChatRoom:
          getOnLineChatRoom(id);
          break;
      }

      if (flag){
        JSONData jsonData=promiseUtil.await(JSONData.class);
        return jsonData;
      }
      else{
        return null;
      }

    }
    finally {
        promiseUtil.release(JSONData.class);
    }

  }
  public void sendMessage(String msg){
    long id=promiseUtil.newLock(JSONData.class);
    try{
      TextMessage message=TextMessage.fromText(id,room,uid,msg);
      checkChannel().writeAndFlush(message);
    }
    finally {
      promiseUtil.release(JSONData.class);
    }
  }
  public void sendFile(String filePath){
    File file=new File(filePath);
    if (!file.exists()){
      throw new IllegalStateException("无效文件路径:"+filePath);
    }
    long id=promiseUtil.newLock(JSONData.class);
    try{
      AttachmentMessage message=AttachmentMessage.fromAttachment(id,room,uid,file);
      checkChannel().writeAndFlush(message);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      promiseUtil.release(JSONData.class);
    }
  }


  public void setContext(ChannelHandlerContext ctx) {
    this.ctx = ctx;
  }

  public void output(String content){
    System.out.println(content);
  }
  public void showHelp(){
    StringBuilder sb=new StringBuilder();
    for (ChatCommand v:ChatCommand.values()){
      /*if (v==ChatCommand.logout||v==ChatCommand.exit){
        sb.append("!"+v.getValue());
      }
      else*/ {
        sb.append(v.getValue());
      }
       switch (v){
         case createRoom:
           sb.append(" <chatroom>");
           break;
         case removeChatRoom:
           sb.append(" <chatroom>");
           break;
         case getOnLineUserList:
           sb.append(" [chatroom]");
           break;
         case login:
           sb.append(" <user> <password>");
           break;
         case enterRoom:
           sb.append(" <chatroom>");
           break;
         case sendFile:
           sb.append(" <filepath>");
           break;
         case fetchFile:
           sb.append(" <file id>");
           break;
       }
       sb.append("\n");
    }
    output(sb.toString());
    showPrompt();
  }
  public void login(long id,String uid,String password){
    CommandMessage commandMessage=CommandMessage.fromCommand(id,uid,"login "+uid+"\n"+password);
    checkChannel().writeAndFlush(commandMessage);
    //this.uid=uid;
  }
  public void logout(long id){
    checkChannel().writeAndFlush(CommandMessage.fromCommand(id,uid, ChatCommand.logout.getValue()));
  }
  public void exitRoom(long id){
    checkChannel().writeAndFlush(CommandMessage.fromCommand(id,uid, ChatCommand.exit.getValue()));
  }
  public void createRoom(long id,String chatRoom){
    checkChannel().writeAndFlush(CommandMessage.fromCommand(id,uid, ChatCommand.createRoom.getValue()+" "+chatRoom));
  }
  public void removeChatRoom(long id,String chatRoom){
    checkChannel().writeAndFlush(CommandMessage.fromCommand(id,uid, ChatCommand.removeChatRoom.getValue()+" "+chatRoom));
  }
  public void enterRoom(long id,String chatRoom){
    checkChannel().writeAndFlush(CommandMessage.fromCommand(id,uid, ChatCommand.enterRoom.getValue()+" "+chatRoom));
  }
  public void fetchFile(long id,String md5){
    checkChannel().writeAndFlush(CommandMessage.fromCommand(id,uid, ChatCommand.fetchFile.getValue()+" "+md5));
  }
  public void getOnLineUserList(long id,String ... chatRoom){
    checkChannel().writeAndFlush(CommandMessage.fromCommand(id,uid, ChatCommand.getOnLineUserList.getValue()
            +(chatRoom.length==0?"":" "+chatRoom[0])));
  }
  public void getOnLineChatRoom(long id){
    checkChannel().writeAndFlush(CommandMessage.fromCommand(id,uid, ChatCommand.getOnLineChatRoom.getValue()));
  }
  public void showResult(JSONData result){
    output(result.getErrCode()==0?result.getResult().toString():result.getMessage());
  }
  public void proc(ChatMessage message) throws IOException {
    CodeConsts.MessageType messageType= CodeConsts.MessageType.fromValue(message.getProperties().getSClass());
    switch (messageType){
      case log:
        output("");
        List<ChatMessage> logs= (List<ChatMessage>) message.getData();
        for (ChatMessage log : logs) {
          if (log instanceof TextMessage) {
            output(String.format("%s %tT: %s", log.getProperties().getUuid(), new Date((Long) (log.getProperties().getExtParams().get("time"))), log.getData().toString()));
          }
          else if (log instanceof AttachmentMessage){
            if (log.getData()==null) {
              output(String.format("%s %tT: <附件:%s,id:%s>", log.getProperties().getUuid(), new Date((Long) (log.getProperties().getExtParams().get("time"))),
                      log.getProperties().getExtParam("file").toString(), log.getProperties().getMD5()));
            }
            else{
            }
          }
        }
        break;
      case attachment:
        String tempFile= FileUtils.getTempDirectoryPath()+File.separator+message.getProperties().getExtParam("file");
        FileUtils.writeByteArrayToFile(new File(tempFile), (byte[]) message.getData());
        output(String.format("已保存至:"+tempFile));
        break;
    }
  }
}
